package com.yun.util;

import org.apache.commons.io.FileUtils;
import org.smslib.Message;
import org.smslib.OutboundMessage;
import org.smslib.SMSLibException;
import org.smslib.Service;
import org.smslib.helper.CommPortIdentifier;
import org.smslib.helper.SerialPort;
import org.smslib.modem.SerialModemGateway;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.List;

import static java.io.File.separator;


public class SmsCat {

    private static final int BAUD_RATE = 9600;

    //短信猫服务
    //static 懒加载，对安管减少无关资源消耗
    private static Service smsService = null;

    //短信猫串口
    private static String smsCatPort;


    /**
     * 短信猫发送
     * @param title             标题
     * @param content           内容
     * @param csaSmsPhoneList     电话号码集合
     * @throws SMSLibException
     * @throws InterruptedException
     */
    public static void sendSms(String title, String content, List<String> csaSmsPhoneList) throws SMSLibException, InterruptedException {
        if (smsService == null) {
            smsService = Service.getInstance();
        }
        content = title + "\n" + content;
        //AppLogger.processorLog(Log.LOG_LEVEL_INFO, "准备发送短信" + "，收件人列表：" + DataUtil.list2String(csaSmsPhoneList, ","));
        if (smsCatPort==null) {
            smsCatPort = getSmsCatPort();
            if (smsCatPort==null) {
                //异常 throw new SMSLibException("未扫描到短信猫设备...");
            }
        }
        SerialModemGateway gateway = new SerialModemGateway("modem", smsCatPort, 9600, "", "");
        // 设置true，表示该网关可以发送短信
        gateway.setOutbound(true);
        // ---------------------- 将设备加到服务中----------------------
        smsService.addGateway(gateway);
        // ------------------------- 启动服务 -------------------------
        //启用轮循模式
        Service.getInstance().S.SERIAL_POLLING = true;
        try {
            smsService.startService();
        } catch (IOException e) {
            e.printStackTrace();
            //异常 throw new SMSLibException("短信猫服务启动失败...");
        }
        //------------------------- 发送短信 -------------------------
        boolean allSuccess = true;
        StringBuilder errInfo = new StringBuilder();
        for (String recipient : csaSmsPhoneList) {
            OutboundMessage message = new OutboundMessage(recipient, content);
            message.setEncoding(Message.MessageEncodings.ENCUCS2);
            try {
                boolean success = smsService.sendMessage(message);
                if (allSuccess) {
                    allSuccess = success;
                }
            } catch (Exception e) {
                //logger.info("发送短信到 {} 失败: {}", recipient, e);
                e.printStackTrace();
                allSuccess = false;
            }
            if (errInfo.length() != 0) {
                errInfo.append(",");
            }
            errInfo.append("发送短信到 " + recipient + " 失败");
        }
        // ------------------------- 关闭服务 -------------------------
        try {
            smsService.stopService();
        } catch (IOException e) {
            e.printStackTrace();
            if (allSuccess) {
                //logger.warn("短信猫服务关闭失败...");
            } else {
                //throw new SMSLibException(errInfo.toString());
            }
        }
        //关闭串口,确保再次调用时能够发送短信
        smsService.removeGateway(gateway);
        if (allSuccess) {
            return;
        } else {
            //throw new SMSLibException(errInfo.toString());
        }
    }




    private static String getSmsCatPort() {
        //判断当前设备占用的串口，以及波特率等参数  当前串口有设备的将参数得到 配置到CasSmsProcessor的网关参数中
        //logger.info("获取短信猫设备串口号...");
        CommPortIdentifier portId;
        Enumeration<?> portList;
        portList = CommPortIdentifier.getPortIdentifiers();

        String result = null;
        while (portList.hasMoreElements()) {
            portId = (CommPortIdentifier) portList.nextElement();
            if (portId.getPortType() != CommPortIdentifier.PORT_SERIAL) {
                continue;
            }
            String port = portId.getName();

            SerialPort serialPort;
            serialPort = portId.open("testPost", 100);
            serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN);
            serialPort.setSerialPortParams(BAUD_RATE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
            serialPort.enableReceiveTimeout(500);
            try (InputStream inStream = serialPort.getInputStream(); OutputStream outStream = serialPort.getOutputStream()) {
                int c;
                outStream.write(65);
                outStream.write(84);
                outStream.write(13);
                String response = "";
                for (c = inStream.read(); c != -1; c = inStream.read()) {
                    response = response + (char) c;
                }

                if (response.indexOf("OK") >= 0) {
                    outStream.write(65);
                    outStream.write(84);
                    outStream.write(43);
                    outStream.write(67);
                    outStream.write(71);
                    outStream.write(77);
                    outStream.write(77);
                    outStream.write(13);
                    response = "";
                    for (c = inStream.read(); c != -1; c = inStream.read()) {
                        response = response + (char) c;
                    }
                    //logger.info("发现串口设备: {}", response.split("\\s+OK\\s+")[0].trim());
                    if (response.contains("SIMCOM")) {
                        result = port;
                        break;
                    }
                } else {
                    //logger.info("串口 {} 没有发现设备!", portId.getName());
                }
            } catch (IOException e) {
                //logger.info("没有发现串口设备!");
            } finally {
                serialPort.close();
            }
        }
        return result;
    }

    /**
     * 短信猫配置
     */
    private void initCatConfig() {
        // 检查驱动
        String javaHome = System.getProperty("java.home");
        // 判断 windows 还是 Linux
        String os = System.getProperty("os.name").toLowerCase();
        try {
            if (os.contains(OS_WINDOWS)) {
                File parallelDll = new File(javaHome + separator + "bin" + separator + WINDOWS_RXTX_PARALLEL_DLL);
                if (!parallelDll.exists()) {
                    //logger.info("当前 {} 系统 Java 路径中不存在 {}, 初始化...", os, parallelDll.getAbsolutePath());
                    InputStream parallelIS = this.getClass().getClassLoader().getResourceAsStream("lib/" + WINDOWS_RXTX_PARALLEL_DLL);
                    FileUtils.copyInputStreamToFile(parallelIS, parallelDll);
                }

                File serialDll = new File(javaHome + separator + "bin" + separator + WINDOWS_RXTX_SERIAL_DLL);
                if (!serialDll.exists()) {
                    //logger.info("当前 {} 系统 Java 路径中不存在 {}, 初始化...", os, serialDll.getAbsolutePath());
                    InputStream serialIS = this.getClass().getClassLoader().getResourceAsStream("lib/" + WINDOWS_RXTX_SERIAL_DLL);
                    FileUtils.copyInputStreamToFile(serialIS, serialDll);
                }
            } else {
                // linux
                File serialSo = new File(javaHome + separator + "lib" + separator + "amd64" + separator + LINUX_LIBRXTX_SERIAL_SO);
                if (!serialSo.exists()) {
                    //logger.info("当前 {} 系统 Java 路径中不存在 {}, 初始化...", os, serialSo.getAbsolutePath());
                    InputStream serialIS = this.getClass().getClassLoader().getResourceAsStream("lib/" + LINUX_LIBRXTX_SERIAL_SO);
                    FileUtils.copyInputStreamToFile(serialIS, serialSo);
                }
            }
            //logger.info("初始化短信猫配置成功...");
        } catch (IOException e) {
            //logger.error("初始化短信猫依赖库失败{}...",e.getMessage());
        }
    }

    // windows 系统
    private static final String OS_WINDOWS = "windows";

    //linux 系统
    @SuppressWarnings("unused")
    private static final String OS_LINUX = "linux";

    //window parallel 库名称
    private static final String WINDOWS_RXTX_PARALLEL_DLL = "rxtxParallel.dll";

    //window 串口库名称
    private static final String WINDOWS_RXTX_SERIAL_DLL = "rxtxSerial.dll";

    //linux 串口库名称
    private static final String LINUX_LIBRXTX_SERIAL_SO = "librxtxSerial.so";
}
